using System;
using System.Collections.Generic;
using System.Xml;
using System.Text;
using System.Text.RegularExpressions;
using System.ComponentModel;

namespace LogAnalyzer
{
    public class GrabFilter : FilterBase
    {
        bool _isRegularExpression = false;
        bool _isCaseSensitive = false;
        string _queryString = "*";
        Regex _filterRegEx;
        private GrabAction _matchAction = GrabAction.Accept;
        private GrabAfterMatchAction _afterMatchAction = GrabAfterMatchAction.GoOn;



        public GrabFilter()
        {
            ReCreateRegEx();
        }
        

        private void ReCreateRegEx()
        {
            _filterRegEx = null;

            string pattern = _queryString;
            if (!_isRegularExpression)
            {
                pattern = Regex.Escape(pattern).Replace(@"\?", ".").Replace(@"\*", ".*");
            }

            RegexOptions options = new RegexOptions();
            if (!_isCaseSensitive) options |= RegexOptions.IgnoreCase;

            _filterRegEx = new Regex(pattern, options);
        }
        

        [Category("a.  Filter parameters")]
        [DisplayName("Query string")]
        [Description("Set the query for the filter; it can be a regular expression a or simple string with wildcards (*,?)")]
        public string QueryString
        {
            get { return _queryString; }
            set
            {
                string old = _queryString;
                _queryString = value;
                try
                {
                    ReCreateRegEx();
                }
                catch
                {
                    _queryString = old;
                    throw;
                }
            }
        }

        [Category("a.  Filter parameters")]
        [DisplayName("Is case sensitive")]
        [Description("Set if query os case sensitive or not")]
        public bool IsCaseSensitive
        {
            get { return _isCaseSensitive; }
            set
            {
                bool old = _isCaseSensitive;
                _isCaseSensitive = value;
                try
                {
                    ReCreateRegEx();
                }
                catch
                {
                    _isCaseSensitive = old;
                    throw;
                }
            }
        }

        [Category("a.  Filter parameters")]
        [DisplayName("Is a regular expression")]
        [Description("Set if query is a regular expression (true) or a simple text with wildcards (false)")]
        public bool IsRegularExpression
        {
            get { return _isRegularExpression; }
            set
            {
                bool old = _isRegularExpression;
                _isRegularExpression = value;
                try
                {
                    ReCreateRegEx();
                }
                catch
                {
                    _isRegularExpression = old;
                    throw;
                }
            }
        }
        
        [Category("b.  Behaviour")]
        [DisplayName("If match")]
        [Description("Specify filter action if line matches filter")]
        public GrabAction MatchAction
        {
            get { return _matchAction; }
            set { _matchAction = value; }
        }

        [Category("b.  Behaviour")]
        [DisplayName("If match then")]
        [Description("Specify the action after this filter if line matches")]
        public GrabAfterMatchAction AfterMatchAction
        {
            get { return _afterMatchAction; }
            set { _afterMatchAction = value; }
        }



        internal Regex InnerRegEx
        {
            get { return _filterRegEx; }
        }



        public override void SaveConfig(System.Xml.XmlNode nodeFilter)
        {
            XmlDocument xml = nodeFilter.OwnerDocument;

            nodeFilter.Attributes.Append(xml.CreateAttribute("q")).Value = _queryString;
            nodeFilter.Attributes.Append(xml.CreateAttribute("cs")).Value = _isCaseSensitive.ToString();
            nodeFilter.Attributes.Append(xml.CreateAttribute("re")).Value = _isRegularExpression.ToString();
            nodeFilter.Attributes.Append(xml.CreateAttribute("act")).Value = _matchAction.ToString();
            nodeFilter.Attributes.Append(xml.CreateAttribute("then")).Value = _afterMatchAction.ToString();
        }

        public override void LoadConfig(System.Xml.XmlNode filterNode)
        {
            _queryString = filterNode.Attributes["q"].Value;
            _isCaseSensitive = bool.Parse(filterNode.Attributes["cs"].Value);
            _isRegularExpression = bool.Parse(filterNode.Attributes["re"].Value);
            _matchAction = (GrabAction)Enum.Parse(typeof(GrabAction), filterNode.Attributes["act"].Value);
            _afterMatchAction = (GrabAfterMatchAction)Enum.Parse(typeof(GrabAfterMatchAction), filterNode.Attributes["then"].Value);

            ReCreateRegEx();
        }

        public override string ToString()
        {
            string s = "";

            switch (_matchAction)
            {
                case GrabAction.Accept: s += "Acc&"; break;
                case GrabAction.Discard: s += "Dis&"; break;
            }
            switch (_afterMatchAction)
            {
                case GrabAfterMatchAction.GoOn: s += "GoOn:"; break;
                case GrabAfterMatchAction.StopHere: s += "Stop:"; break;
            }

            return s + QueryString;
        }

        public override FilterBase Clone()
        {
            return (FilterBase)this.MemberwiseClone();
        }

    }

    public enum GrabAction
    {
        Accept,
        Discard,
    }

    public enum GrabAfterMatchAction
    {
        GoOn,
        StopHere
    }

}
